#include "CharacterServer.h"

#include <iostream>
#include <string>

#include "Conversion.h"
#include "GemColour.h"

#define CHARACTER_IMAGE_HEIGHT 30.0
#define CHARACTER_IMAGE_WIDTH 27.0

#define Y_IMPULSE 3.0

using namespace std;


/*Surcharges operateur*/
sf::Packet& operator <<(sf::Packet& packet, const CharacterServer& characterServer) {	
	sf::Vector2f position = box2dToSfmlPosition(characterServer.playerPosition);
	
	return packet << position.x << position.y
		<< characterServer.chDirection << characterServer.chAction
		<< characterServer.nbPoints << characterServer.youwin;
}

CharacterServer::CharacterServer(float posX, float posY) {
	playerWidth = sfmlToBox2dLength(27.0/2);
	playerHeight = sfmlToBox2dLength(30.0/2);

	nbPoints = 0;

	/* B2D Initialisation */
	playerPosition = sfmlToBox2dPosition(sf::Vector2f(posX + (CHARACTER_IMAGE_WIDTH/2), 
		posY + (CHARACTER_IMAGE_HEIGHT/2)));
	//sfmlToBox2dPosition(sf::Vector2f(500 + (CHARACTER_WIDTH/2), 100 + (CHARACTER_HEIGHT/2)));

	chDirection = RIGHT;
	chAction = FACING;

	m_contacting = false;
	type = PLAYER;

	youwin = false;
}

void CharacterServer::initialiseB2D(b2World* world) {
	characterBodyDef.type = b2_dynamicBody;
	
	dynamicBox.SetAsBox(playerWidth, playerHeight);

	characterBodyDef.position.Set(playerPosition.x, playerPosition.y);

	body = world->CreateBody(&characterBodyDef);

	
	fixtureDef.shape = &(dynamicBox); 
	fixtureDef.density = 1.0f; 
	fixtureDef.friction = 0.3f;

	body->CreateFixture(&fixtureDef);
	body->SetUserData(this);
}

void CharacterServer::send( sf::TcpSocket& socket ) {
	sf::Packet packet;
	packet << *this;
	socket.send(packet);
}


/*Fonction qui test si on a atteri apres un saut*/
void CharacterServer::beforeJump() {

	if(testJump == false && body->GetLinearVelocity().y < 0) {
		testJump = true;
	}
	
	if(testJump == true && body->GetLinearVelocity().y > 0 ) {

		if(chAction == JUMPING) {
			chAction = FACING;
		} 
		if(chAction == JUMPRUNNING) {
			chAction = RUNNING;
		}
	}


}

void CharacterServer::testFall() {
	//TODO a utiliser dans l'affichage
	/*if(playerPosition.y < 0) {
		chAction = DEAD;
	}*/
}

void CharacterServer::die() {
	printf("Player is dead !\n");
	chAction = DEAD;
	chDirection = NONE;
	body->ApplyLinearImpulse(b2Vec2(0.0f, Y_IMPULSE), body->GetWorldCenter(), true);
	body->GetFixtureList()->SetDensity(0.0f);
	body->GetFixtureList()->SetFriction(0.0f);
	body->GetFixtureList()->SetSensor(true);
	body->ResetMassData(); 

}

void CharacterServer::win() {
	youwin = true;
	printf("Player won !\n");
}

void CharacterServer::collect(GemServer* gem, ServerWorldObjects* swo) {
	if (!gem->picked) {
		gem->disappear();

		nbPoints += gem->points;

		/*On augmente la taille du tableau des gems MAJ*/
		if(gem->colour == YELLOW) {
			swo->yellowGemsUpNb++;
			if(swo->yellowGemsUpdate == NULL) {
				swo->yellowGemsUpdate = (int*)malloc(sizeof(int));
			}
			else {
				swo->yellowGemsUpdate = (int*)realloc(swo->yellowGemsUpdate, sizeof(int) * swo->yellowGemsUpNb);
			}
		
			swo->yellowGemsUpdate[swo->yellowGemsUpNb - 1] = gem->id;
		} else if(gem->colour == PURPLE) {
			swo->violetGemsUpNb++;
			if(swo->violetGemsUpdate == NULL) {
				swo->violetGemsUpdate = (int*)malloc(sizeof(int));
			}
			else {
				swo->violetGemsUpdate = (int*)realloc(swo->violetGemsUpdate, sizeof(int) * swo->violetGemsUpNb);
			}
		
			swo->violetGemsUpdate[swo->violetGemsUpNb - 1] = gem->id;
		}


		printf("Gem collected ! Player points = %d\n", nbPoints);
	}
}

void CharacterServer::startContact() {
	m_contacting = true;
}

void CharacterServer::endContact() {
	m_contacting = false;
}

bool CharacterServer::hasWon() {
	return youwin;
}

void CharacterServer::stop() {
	body->GetFixtureList()->SetDensity(1.0f);
	body->GetFixtureList()->SetFriction(0.0f);
	body->GetFixtureList()->SetSensor(true);
	body->ResetMassData(); 
}